﻿/*
 * @Autor: PK
 * @Date: 2022/01/25 11:48:SS
 */

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using O2DESNet;
using ShkSimulation.core.exceptions;

namespace ShkSimulation.core.optimization.extractor {

	public class NamedCellPointGroup {

		public IReadOnlyDictionary<string, Dictionary<string, CellPoint>> Location =>
			location.AsReadOnly();
		
		public Dictionary<string, List<CellPoint>> ListLocation =>
			location.ToDictionary(each => each.Key, each => new List<CellPoint>(each.Value.Values));
		
		internal Dictionary<string/*tableName*/, Dictionary<string/*CellPoint Name*/, CellPoint>> location  { get; set; }
		
		internal ISet<string> UniqueName { get; private set; }
		
		internal ISet<string> UniquePoint { get; private set; }

		public NamedCellPointGroup() {
			this.location = new Dictionary<string, Dictionary<string, CellPoint>>();
			this.UniqueName = new HashSet<string>();
			this.UniquePoint = new HashSet<string>();
		}

		public ImmutableSortedSet<string> GetSortedName() {
			return location.Values.SelectMany(each => each.Keys).ToImmutableSortedSet();
		}

		public bool IsPointRepeat(string tableName, string name, int row, int column) {
			if (UniqueName.Contains(name)) {
				return true;
			}
			string point = $"{tableName}-{row}-{column}";
			if (UniquePoint.Contains(point)) {
				return true;
			}
			return false;
		}
		
		private string CheckPointRepeat(string tableName, CellPoint valuePoint) {
			if (UniqueName.Contains(valuePoint.Name)) {
				throw new ErrorParamException("属性名字不能重复：" + valuePoint.Name);
			}
			string point = $"{tableName}-{valuePoint.Row}-{valuePoint.Column}";
			if (UniquePoint.Contains(point)) {
				throw new ErrorParamException($"同一个表的定位数据不能重复：{valuePoint.Name}");
			}
			return point;
		}

		public NamedCellPointGroup AddNamedCellPoint(string tableKey, CellPoint valuePoint) {
			var key = CheckPointRepeat(tableKey, valuePoint);
			UniqueName.Add(valuePoint.Name);
			UniquePoint.Add(key);
			if (!location.ContainsKey(tableKey)) {
				location.Add(tableKey, new Dictionary<string, CellPoint>());
			}
			location[tableKey][valuePoint.Name] = valuePoint;
			return this;
		}
		
		public NamedCellPointGroup AddNamedCellPoints(string tableKey, Dictionary<string, CellPoint> points) {
			if (!location.ContainsKey(tableKey)) {
				location.Add(tableKey, new Dictionary<string, CellPoint>());
			}
			foreach (var pair in points) {
				if (UniqueName.Contains(pair.Key)) {
					throw new ErrorParamException("属性名字不能重复：" + pair.Key);
				}
				var key = CheckPointRepeat(tableKey, pair.Value);
				UniquePoint.Add(key);
				UniqueName.Add(pair.Key);
				location[tableKey][pair.Key] = pair.Value;
			}
			return this;
		}
		
		public NamedCellPointGroup RemoveTable(string tableKey) {
			if (!location.ContainsKey(tableKey)) {
				return this;
			}
			foreach (var key in location[tableKey].Keys) {
				var point = location[tableKey][key];
				string pointInfo = $"{tableKey}-{point.Row}-{point.Column}";
				UniqueName.Remove(key);
				UniquePoint.Remove(pointInfo);
			}
			location.Remove(tableKey);
			return this;
		}
		
		public NamedCellPointGroup RemoveCellPointsByName(string tableKey, string valueName) {
			if (!location.ContainsKey(tableKey)) {
				return this;
			}
			if (!location[tableKey].ContainsKey(valueName)) {
				return this;
			}
			location[tableKey].Remove(valueName);
			var point = location[tableKey][valueName];
			string pointInfo = $"{tableKey}-{point.Row}-{point.Column}";
			UniqueName.Remove(valueName);
			UniquePoint.Remove(pointInfo);
			return this;
		}

		public override string ToString() {
			List<string> names = location.Values.SelectMany(each => each.Keys).ToList();
			return string.Join(", ", names);
		}

	}

}